package xxl.signals.base.valuelists 
{
	import xxl.signals.core.ISlot;
	/**
	 * @author XXL
	 */
	public class SlotList 
	{
		public static const NIL:SlotList = new SlotList(null, null);
		
		public var head:ISlot;
		public var tail:SlotList;
		public var nonEmpty:Boolean = false;
		
		public function SlotList(head:ISlot, tail:SlotList = null) 
		{
			if (!head && !tail)
			{
				if (NIL)
				{
					throw new ArgumentError("head不能为空");
				}
				nonEmpty = false;
			}
			else if (!head)
			{
				throw new ArgumentError("head不能为空");
			}
			else
			{
				this.head = head;
				this.tail = tail || NIL;
				nonEmpty = true;
			}
		}
		
		public function get length():int
		{
			if (!nonEmpty)
			{
				return 0;
			}
			if (tail == NIL)
			{
				return 1;
			}
			var result:int = 0;
			var p:SlotList = this;
			while (p.nonEmpty)
			{
				++result;
				p = p.tail;
			}
			return result;
		}
		
		/**
		 * 在列表最前面加上，运行速度O(1)
		 * @param	slot
		 * @return
		 */
		public function prepend(slot:ISlot):SlotList
		{
			return new SlotList(slot, this);
		}
		
		/**
		 * 在列表尾部追加，运行速度O(n)
		 * @param	slot
		 * @return
		 */
		//public function append(slot:ISlot):SlotList
		//{
			//if (!slot)
			//{
				//return this;
			//}
			//if (!nonEmpty)
			//{
				//return new SlotList(slot);
			//}
			//if (tail == NIL)
			//{
				//return new SlotList(slot).prepend(head);
			//}
			//
			//const wholeClone:SlotList = new SlotList(head);
			//var subClone:SlotList = wholeClone;
			//var current:SlotList = tail;
			//while (current.nonEmpty)
			//{
				//subClone = subClone.tail = new SlotList(current.head);
				//current = current.tail;
			//}
			//subClone.tail = new SlotList(slot);
			//return wholeClone;
		//}
		
		public function filterNot(listener:Function):SlotList
		{
			if (!nonEmpty || listener == null)
			{
				return this;
			}
			if (listener == head.listener)
			{
				return tail;
			}
			const wholeClone:SlotList = new SlotList(head);
			var subClone:SlotList = wholeClone;
			var current:SlotList = tail;
			
			while (current.nonEmpty)
			{
				if (current.head.listener == listener)
				{
					subClone.tail = current.tail;
					return wholeClone;
				}
				
				subClone = subClone.tail = new SlotList(current.head);
				current = current.tail;
			}
			return this;
		}
		
	}

}